#ifndef __WIZ_BNF_PARSER_REAL_IMPL_HPP__SHANHAOBO_19800429__
#define __WIZ_BNF_PARSER_REAL_IMPL_HPP__SHANHAOBO_19800429__

#include "./WizBNFParserSign.hpp"

namespace Wiz
{
    namespace BNF
    {
        namespace Parser
        {
            namespace Impl
            {
                namespace Real
                {
                    template <typename ResultT, typename NumberT, typename PoliciesT>
                    struct Type
                    {
                        typedef Type        tThis;
                        typedef ResultT     tResult;
                        typedef PoliciesT   tPolicies;
                        typedef NumberT     tNumber;

                        template <typename ScannerT>
                        tResult ParseMain(ScannerT const& Scan) const
                        {
                            typedef typename ::Wiz::BNF::Parser::Result<::Wiz::BNF::Parser::Sign::Type, ScannerT>::tType            tSignMatch;
                            typedef typename ::Wiz::BNF::Parser::Result<::Wiz::BNF::Parser::Char::Check::Type<>, ScannerT>::tType   tExpMatch;
                            typedef typename ScannerT::tIterator                                                                    tIterator;
                            if (Scan.AtEnd())
                            {
                                return Scan.NoMatch();
                            }
                            tIterator StartItr(Scan.m_Curr);
                            ::Wiz::Size::Type ResultLen(0);
                            tNumber Number(0);

                            ::Wiz::Bool::Type IsNeg = ::Wiz::Bool::False;
                            tSignMatch SignMatch = tPolicies::ParseSign(Scan);
                            if (SignMatch.IsValid())
                            {
                                IsNeg = SignMatch.Value();
                                ResultLen = SignMatch.Length();
                            }

                            ::Wiz::Bool::Type GotANumber = ::Wiz::Bool::False;
                            tResult NMatch = tPolicies::ParseN(Scan);
                            if (NMatch.IsValid())
                            {
                                GotANumber = ::Wiz::Bool::True;
                                Number = NMatch.Value();
                                ResultLen += NMatch.Length();
                            }

                            if ((GotANumber == ::Wiz::Bool::False) && (tPolicies::AllowLeadingDot == ::Wiz::Bool::False))
                            {
                                return Scan.NoMatch();
                            }

                            if (IsNeg)
                            {
                                Number = -Number;
                            }

                            tExpMatch ExpMatch;
                            if (tPolicies::ParseDot(Scan))
                            {
                                ResultLen++;
                                tResult FracNMatch = tPolicies::ParseFracN(Scan);
                                if (FracNMatch.IsValid())
                                {
                                    tNumber FracN = FracNMatch.Value() * ::pow(tNumber(10), tNumber(-FracNMatch.Length()));
                                    if (IsNeg)
                                    {
                                        Number -= FracN;
                                    }
                                    else
                                    {
                                        Number += FracN;
                                    }
                                    ResultLen += FracNMatch.Length();

                                }
                                else if ((GotANumber == ::Wiz::Bool::False) || (tPolicies::AllowTrailingDot == ::Wiz::Bool::False))
                                {
                                    return Scan.NoMatch();
                                }

                                ExpMatch = tPolicies::ParseExp(Scan);
                            }
                            else
                            {
                                if (GotANumber == ::Wiz::Bool::False)
                                {
                                    return Scan.NoMatch();
                                }

                                ExpMatch = tPolicies::ParseExp(Scan);
                                if (tPolicies::ExpectDot && ExpMatch.NotValid())
                                {
                                    return Scan.NoMatch();
                                }
                            }

                            if (ExpMatch.IsValid())
                            {
                                ResultLen += ExpMatch.Length();

                                tResult ExpNMatch = tPolicies::ParseExpN(Scan);
                                if (ExpNMatch.IsValid())
                                {
                                    Number *= ::pow(tNumber(10), tNumber(ExpNMatch.Value()));
                                    ResultLen += ExpNMatch.Length();
                                }
                                else
                                {
                                    return Scan.NoMatch();
                                }
                            }

                            return Scan.CreateMatch(ResultLen, Number, StartItr, Scan.m_Curr);
                        }

                        template <typename ScannerT>
                        static tResult Parse(ScannerT const& Scan)
                        {
                            static tThis s_This;
                            return ::Wiz::BNF::Parser::Impl::ImplicitLexemeParse<tResult>(s_This, Scan, Scan);
                        }
                    };
                } /// end of namespace Real
            } /// end of namespace Impl
        } /// end of namespace Parser
    } /// end of namespace BNF
} /// end of namespace Wiz

#endif /*__WIZ_BNF_PARSER_REAL_IMPL_HPP__SHANHAOBO_19800429__*/
